
Imports System.IO

Public Module streamhandle

    Public Const defaultRetryTimes As Int64 = 64

    Public Function closeBinaryWriter(Of t As BinaryWriter)(ByRef writer As t) As Boolean
        On Error Resume Next

        If Not writer Is Nothing Then
            writer.Flush()
            closestream(writer.BaseStream())
            writer.Close()

            writer = Nothing
            Return True
        Else
            Return False
        End If
    End Function

    Public Function closeBinaryReader(Of t As BinaryReader)(ByRef reader As t) As Boolean
        On Error Resume Next

        If Not reader Is Nothing Then
            closestream(reader.BaseStream())
            reader.Close()

            reader = Nothing
            Return True
        Else
            Return False
        End If
    End Function

    Public Function closereader(Of t As TextReader)(ByRef reader As t) As Boolean
        On Error Resume Next

        If Not reader Is Nothing Then
            Dim istream As Stream = Nothing
            istream = convertor.cast(Of StreamReader)(reader, False).BaseStream
            closestream(istream)
            reader.Close()
            istream = Nothing
#If Not (PocketPC OrElse Smartphone) Then
            reader.Dispose()
#End If
            reader = Nothing
            Return True
        Else
            Return False
        End If
    End Function

    Public Function closewriter(Of t As TextWriter)(ByRef writer As t) As Boolean
        On Error Resume Next

        If Not writer Is Nothing Then
            writer.Flush()
            Dim ostream As Stream = Nothing
            ostream = convertor.cast(Of StreamWriter)(writer, False).BaseStream
            closestream(ostream)
            writer.Close()
            ostream = Nothing
#If Not (PocketPC OrElse Smartphone) Then
            writer.Dispose()
#End If
            writer = Nothing
            Return True
        Else
            Return False
        End If
    End Function

    Public Function closestream(ByRef oper As TextWriter) As Boolean
        Return closewriter(oper)
    End Function

    Public Function closestream(ByRef oper As TextReader) As Boolean
        Return closereader(oper)
    End Function

    Public Function closestream(ByRef oper As Stream) As Boolean
        On Error Resume Next
        If Not oper Is Nothing Then
            oper.Flush()
            oper.Close()
#If Not (PocketPC OrElse Smartphone) Then
            oper.Dispose()
#End If

            oper = Nothing
            Return True
        Else
            Return False
        End If
    End Function

    Public Function closestream(ByRef oper As BinaryReader) As Boolean
        Return closeBinaryReader(oper)
    End Function

    Public Function closestream(ByRef oper As BinaryWriter) As Boolean
        Return closeBinaryWriter(oper)
    End Function

#If RETIRED Then
    Public Function closestream(Of t)(ByRef oper As t) As Boolean
        On Error Resume Next

        Dim extCode As Boolean = True
        If Not oper Is Nothing Then
            If TypeOf oper Is TextWriter Then
                Return closewriter(convertor.cast(Of TextWriter)(oper))
            ElseIf TypeOf oper Is TextReader Then
                Return closereader(convertor.cast(Of TextReader)(oper))
            ElseIf TypeOf oper Is Stream Then
                Dim s As Stream = Nothing
                s = convertor.cast(Of Stream)(oper)
                s.Flush()
                s.Close()
#If Not (PocketPC OrElse Smartphone) Then
                s.Dispose()
#End If
                extCode = True
            ElseIf TypeOf oper Is BinaryReader Then
                Return closeBinaryReader(convertor.cast(Of BinaryReader)(oper, True))
            ElseIf TypeOf oper Is BinaryWriter Then
                Return closeBinaryWriter(convertor.cast(Of BinaryWriter)(oper, True))
            Else
                extCode = False
            End If
            oper = Nothing
        Else
            extCode = False
        End If

        Return extCode
    End Function
#End If

    Public Function writestream(ByVal s As Stream, ByVal buff() As Byte, _
                                Optional ByVal offsetInBuff As Int32 = 0, _
                                Optional ByVal lengthInBuff As Int32 = npos, _
                                Optional ByVal retrytimes As Int32 = npos, _
                                Optional ByVal starttime As Int64 = npos, _
                                Optional ByVal holdtime As Int64 = npos, _
                                Optional ByVal sleeptime As Int64 = npos) As Boolean
        assert(Not buff Is Nothing)
        assert(Not s Is Nothing, "stream is nothing")
        assert(s.CanWrite, "stream cannot write")

        If starttime = npos Then
            starttime = ticksToMilliseconds(Now.Ticks)
        End If
        If lengthInBuff = npos Then
            lengthInBuff = buff.Length - offsetInBuff
        End If
        If holdtime <> npos Then
            If retrytimes = npos AndAlso sleeptime > 0 Then
                retrytimes = holdtime \ sleeptime
            End If
            Try
                s.WriteTimeout = holdtime
            Catch
                ' on old version of .net cf, this property is not supported
            End Try
        End If
        If retrytimes <= 0 Then
            retrytimes = defaultRetryTimes
        End If

        Dim i As Int32
        For i = 0 To retrytimes - 1
            Try
                s.Write(buff, offsetInBuff, lengthInBuff)
                Exit For
            Catch
                If holdtime <> npos Then
                    If ticksToMilliseconds(Now.Ticks) - starttime < holdtime Then
                        If sleeptime <> npos Then
                            sleep(sleeptime)
                        End If
                    Else
                        i = retrytimes
                    End If
                End If
            End Try
        Next

        Return i < retrytimes
    End Function

#If RETIRED Then
    Public Function writestream(ByVal s As Stream, ByVal buff As bytes _
                                , Optional ByVal start As Int32 = 0 _
                                , Optional ByVal length As Int32 = npos _
                                , Optional ByVal retrytimes As Int32 = npos _
                                , Optional ByVal starttime As Int64 = npos _
                                , Optional ByVal holdtime As Int64 = npos _
                                , Optional ByVal sleeptime As Int64 = npos) As Boolean
        If buff Is Nothing OrElse s Is Nothing Then
            Return False
        Else
            Return writestream(s, buff.data, start, length, retrytimes, starttime, holdtime, sleeptime)
        End If
    End Function
#End If

End Module
